package net.cyndeline.GameMap.dataStructure.examinators

import net.cyndeline.GameMap.GridNodeExaminer
import net.cyndeline.NorthEast
import net.cyndeline.MovementDirection
import net.cyndeline.East
import net.cyndeline.SouthEast
import net.cyndeline.SouthWest
import net.cyndeline.West
import net.cyndeline.NorthWest
import net.cyndeline.GameMap.Tile
import net.cyndeline.GameMap.dataStructure.Node

/**
 * Examines a hexagonal grid node.
 */
class HexNodeExaminer[T] extends GridNodeExaminer {
  
  override def canConnectTo(node: Tile, connectTo: Tile): Boolean = {
	if (connectTo.y % 2 != 0) // y is odd
	  node match {
  	  	case n: Node if (n.x == connectTo.x && n.y == connectTo.y - 1) => true 		// nw
  	  	case n: Node if (n.x == connectTo.x + 1 && n.y == connectTo.y - 1) => true	// ne
  	  	case n: Node if (n.x == connectTo.x - 1 && n.y == connectTo.y) => true		// w
  	  	case n: Node if (n.x == connectTo.x + 1 && n.y == connectTo.y) => true		// e
  	  	case n: Node if (n.x == connectTo.x && n.y == connectTo.y + 1) => true		// sw
  	  	case n: Node if (n.x == connectTo.x + 1 && n.y == connectTo.y + 1) => true	// se
  	  	case _ => false
      }	
    else // y is even
      node match {
    	case n: Node if (n.x == connectTo.x - 1 && n.y == connectTo.y - 1) => true 	// nw
    	case n: Node if (n.x == connectTo.x && n.y == connectTo.y - 1) => true		// ne
    	case n: Node if (n.x == connectTo.x - 1 && n.y == connectTo.y) => true		// w
    	case n: Node if (n.x == connectTo.x + 1 && n.y == connectTo.y) => true		// e
    	case n: Node if (n.x == connectTo.x - 1 && n.y == connectTo.y + 1) => true	// sw
    	case n: Node if (n.x == connectTo.x && n.y == connectTo.y + 1) => true		// se
    	case _ => false
      }
  }
  
  override def getDirection(node: Tile, comparedTo: Tile): Option[MovementDirection] = {
    if (comparedTo.y % 2 != 0) // y is odd
	  node match {
  	  	case n: Node if (n.x == comparedTo.x && n.y == comparedTo.y - 1) => Option(NorthWest) 		// nw
  	  	case n: Node if (n.x == comparedTo.x + 1 && n.y == comparedTo.y - 1) => Option(NorthEast)	// ne
  	  	case n: Node if (n.x == comparedTo.x - 1 && n.y == comparedTo.y) => Option(West)	// w
  	  	case n: Node if (n.x == comparedTo.x + 1 && n.y == comparedTo.y) => Option(East)		// e
  	  	case n: Node if (n.x == comparedTo.x && n.y == comparedTo.y + 1) => Option(SouthWest)		// sw
  	  	case n: Node if (n.x == comparedTo.x + 1 && n.y == comparedTo.y + 1) => Option(SouthEast)	// se
  	  	case _ => None
      }	
    else // y is even
      node match {
    	case n: Node if (n.x == comparedTo.x - 1 && n.y == comparedTo.y - 1) => Option(NorthWest) 	// nw
    	case n: Node if (n.x == comparedTo.x && n.y == comparedTo.y - 1) => Option(NorthEast)		// ne
    	case n: Node if (n.x == comparedTo.x - 1 && n.y == comparedTo.y) => Option(West)		// w
    	case n: Node if (n.x == comparedTo.x + 1 && n.y == comparedTo.y) => Option(East)		// e
    	case n: Node if (n.x == comparedTo.x - 1 && n.y == comparedTo.y + 1) => Option(SouthWest)	// sw
    	case n: Node if (n.x == comparedTo.x && n.y == comparedTo.y + 1) => Option(SouthEast)		// se
    	case _ => None
      }
  }
  
  override def getNeighborPositions(node: Tile): List[(Int, Int)] = {
	  val offset = if (node.y % 2 == 0) -1 else 1		
	  var positions = List[(Int, Int)]()
	  
    positions ::= (node.x + 1, node.y)
    positions ::= (node.x - 1, node.y)
    positions ::= (node.x, node.y + 1)
    positions ::= (node.x, node.y - 1)
		positions ::= (node.x + offset, node.y + 1)
		positions ::= (node.x + offset, node.y - 1)
	  
	  positions
	}
}